using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using Habanero.Base;
using Habanero.BO.ClassDefinition;
using Habanero.Faces.Base;
using Habanero.Faces.Win;

namespace FireStarterModeller.UI.Relationship
{
    /// <summary>
    /// This wizard step is the second step for creating a new <see cref="DMRelationship"/>. 
    /// This step allows the user to select whether they want to create the Foreign Key Props or not.
    /// And to select the Cardinality of the Relationship
    /// This step is only required when the system did not find the relevant Foreign Key Props.
    /// If the Owning BO and Related BO both have Valid Object Identifiers (Single Prop of type GUID).
    /// then the wizard can create the foreign key else the wizard cannot and the CreateFKCheckBox
    /// will be disabled.
    /// 
    /// </summary>
    public class CreateRelationshipWizardStep2 : WizardStepWin
    {
        private DMRelationshipCreator RelationshipCreator { get; set; }

        private IControlFactory ControlFactory { get; set; }

        public IComboBox CardinalityComboBox { get; private set; }

        public bool IsInitialised { get; private set; }

        public ICheckBox CreateFKCheckBox { get; private set; }

        private ILabel MessageLabel { get; set; }

        public DMRelationship Relationship
        {
            get
            {
                return this.RelationshipCreator == null ? null : this.RelationshipCreator.Relationship;
            }
        }

        public CreateRelationshipWizardStep2(DMRelationshipCreator relationshipCreator,
                                             IControlFactory controlFactory)
        {
            RelationshipCreator = relationshipCreator;
            if (relationshipCreator == null) throw new ArgumentNullException("relationshipCreator");
            if (controlFactory == null) throw new ArgumentNullException("controlFactory");
            ControlFactory = controlFactory;
            CreateFKCheckBox = this.ControlFactory.CreateCheckBox(true);
            CreateFKCheckBox.Text = "Create Foreign Key Property";
            CreateFKCheckBox.CheckAlign = ContentAlignment.TopRight;
            CreateCardinalityComboBox();
            CardinalityComboBox.Width = 80;
            MessageLabel = controlFactory.CreateLabel();
            MessageLabel.Width = 300;
            MessageLabel.Height = 60;


            GridLayoutManager layoutManager = new GridLayoutManager(this,controlFactory);
            layoutManager.SetGridSize(3, 2);
            layoutManager.FixAllRowsBasedOnContents();
            layoutManager.FixColumnBasedOnContents(0);
            layoutManager.AddControl(MessageLabel, 1, 2);
            layoutManager.AddControl(this.CreateFKCheckBox);
            layoutManager.AddControl(controlFactory.CreateLabel());
            layoutManager.AddControl(CardinalityComboBox);
        }

        private void CreateCardinalityComboBox()
        {
            CardinalityComboBox = ControlFactory.CreateComboBox();
            CardinalityComboBox.Items.Add("");
            var enumList = GetEnumDataSource<RelationshipCardinality>();
            foreach (var item in enumList)
            {
                CardinalityComboBox.Items.Add(item);
            }
            CardinalityComboBox.SelectedItem ="OneToMany";
        }

        private static IEnumerable<string> GetEnumDataSource<T>() where T : struct
        {
            Type myEnumType = typeof(T);
            if (myEnumType.BaseType != typeof(Enum))
            {
                throw new ArgumentException("Type T must inherit from System.Enum.");
            }
            string[] enumNames = Enum.GetNames(myEnumType);
            return enumNames.ToList();
        }
        /// <summary>
        /// initialise the wizardstep
        /// </summary>
        public override void InitialiseStep()
        {
            IsInitialised = true;
            var canCreateForeignKey = this.RelationshipCreator.CanCreateForeignKey;
            CreateFKCheckBox.Checked = canCreateForeignKey;
            CreateFKCheckBox.Enabled = canCreateForeignKey;
            var message = "";
            if (this.RelationshipCreator.RelatedDMClass != this.RelationshipCreator.Relationship.OwnerClass)
            {
                message = "No foreign key props found between the related classes.";
                if (this.RelationshipCreator.HasExistingRelationshipBetweenClasses)
                {
                    message =
                        "There is already an existing relationship between these classes. If you continue you will create another relationship.";
                }
                if (canCreateForeignKey)
                {
                    message += Environment.NewLine +
                               " Select whether you want to create a ForeignKey Prop.";
                }
                else
                {
                    message += Environment.NewLine
                               +
                               "The foreign key prop will not be created automatically, since the object Identifiers of both classes do not conform to the standard of being a "
                               + "single Property of type Guid."
                               + Environment.NewLine +
                               "You will have to add a foreign Key Prop to the relevant class manually.";
                }
                message += Environment.NewLine +
                              " Select the Cardinality of the new Relationship.";
                MessageLabel.Text = message;
            }
        }

        /// <summary>
        /// Can move to next wizard step
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public override bool CanMoveOn(out string message)
        {
            CheckInitialised();
            message = "";
//            if (this.MustCreateForeignKey && this.CardinalityComboBox.SelectedItem == null)
//            {
//                message =
//                    "You cannot move on since you have selected to create a ForeignKey but no cardinality has been selected";
//                return false;
//            }    
            if (this.CardinalityComboBox.SelectedItem == null)
            {
                message = "You cannot move on since no cardinality has been selected";
                return false;
            }
            if (this.RelationshipCreator.RelatedDMClass == null)
            {
                message = "You cannot move on since the related class has not been set";
                return false;
            }

            return true;
        }

        public override void MoveOn()
        {
            this.RelationshipCreator.MustCreateForeignKeyProp = this.MustCreateForeignKey;
            SetCardinality();
            this.RelationshipCreator.SetupRelationship();
        }

        public override void UndoMoveOn()
        {
            this.RelationshipCreator.CancelCreatedProperties();
            
        }

        private void SetCardinality()
        {
            if (this.CardinalityComboBox.SelectedItem == null) return;
            var selectedItem = this.CardinalityComboBox.SelectedItem.ToString();
            if (string.IsNullOrEmpty(selectedItem)) return;

            this.RelationshipCreator.RelationshipCardinality = ParseEnum<RelationshipCardinality>(selectedItem);

        }

        private static T ParseEnum<T>(string selectedItem)
        {
            return (T) Enum.Parse(typeof(T), selectedItem);
        }

        /// <summary>
        /// Verifies whether the user can move back from this step.
        /// </summary>
        /// <returns></returns>
        public override bool CanMoveBack()
        {
            return true;
        }

        public override void CancelStep()
        {
            //TODO brett 07 Dec 2009: Implement Cancelling wizard here
        }

        public override string HeaderText
        {
            get { return "Step2: Select Create Foreign Key"; }
        }

        private void CheckInitialised()
        {
            if (!IsInitialised)
            {
                throw new WizardStepNotInitialised("The wizard step " + this.GetType().Name +
                                                   " is not initialised. Please ensure InitialiseStep is called prior to trying to access any methods");
            }
        }

        /// <summary>
        ///  business object that this wizard step is creating
        /// </summary>
        public DMRelationship CreatedRelationship
        {
            get
            {
                CheckInitialised();
                return Relationship;
            }
        }

        /// <summary>
        /// Create FK checked from CheckBox
        /// </summary>
        public bool MustCreateForeignKey
        {
            get { return this.CreateFKCheckBox.Checked; }
        }

    }
}